/*
 * BaseServer.cpp
 * 
 * 服务器基类实现
 */

#include "server/BaseServer.h"
#include "protocol/MessageCodec.h"
#include "protocol/PacketHeader.h"

#include <muduo/base/Logging.h>
#include <muduo/net/InetAddress.h>

using namespace muduo;
using namespace muduo::net;

namespace framework {

BaseServer::BaseServer(const ServerConfig& config)
    : config_(config),
      running_(false) {
    LOG_INFO << "BaseServer created: " << config_.serverName;
}

BaseServer::~BaseServer() {
    LOG_INFO << "BaseServer destroyed";
}

bool BaseServer::init() {
    LOG_INFO << "Initializing server: " << config_.serverName;
    
    // 创建网络服务器
    InetAddress listenAddr(config_.network.ip, config_.network.port);
    networkServer_.reset(new NetworkServer(&loop_, listenAddr, config_.serverName));
    
    // 设置线程数
    networkServer_->setThreadNum(config_.network.threadNum);
    
    // 设置回调
    networkServer_->setSessionConnectedCallback(
        std::bind(&BaseServer::handleSessionConnected, this, _1));
    networkServer_->setSessionDisconnectedCallback(
        std::bind(&BaseServer::handleSessionDisconnected, this, _1));
    networkServer_->setSessionMessageCallback(
        std::bind(&BaseServer::handleSessionMessage, this, _1, _2, _3));
    
    // 调用子类初始化
    if (!onInit()) {
        LOG_ERROR << "User onInit() failed";
        return false;
    }
    
    LOG_INFO << "Server initialized successfully";
    LOG_INFO << "  Listen: " << config_.network.ip << ":" << config_.network.port;
    LOG_INFO << "  Thread Num: " << config_.network.threadNum;
    
    return true;
}

int BaseServer::run() {
    if (!init()) {
        LOG_FATAL << "Server initialization failed";
        return -1;
    }
    
    // 启动服务器
    networkServer_->start();
    
    // 调用子类启动回调
    onStart();
    
    LOG_INFO << "Server started: " << config_.serverName;
    LOG_INFO << "Press Ctrl+C to stop";
    
    running_ = true;
    
    // 进入事件循环（阻塞）
    loop_.loop();
    
    return 0;
}

void BaseServer::stop() {
    LOG_INFO << "Stopping server...";
    
    running_ = false;
    
    // 调用子类停止回调
    onStop();
    
    // 退出事件循环
    loop_.quit();
    
    LOG_INFO << "Server stopped";
}

void BaseServer::sendToClient(uint64_t sessionId,
                              uint16_t msgId,
                              const google::protobuf::Message& msg) {
    // 编码消息
    muduo::net::Buffer buf;
    protocol::MessageCodec::encode(msgId, msg, &buf);
    
    // 发送
    networkServer_->send(sessionId, buf.retrieveAllAsString());
}

void BaseServer::broadcast(uint16_t msgId,
                          const google::protobuf::Message& msg) {
    // 编码消息
    muduo::net::Buffer buf;
    protocol::MessageCodec::encode(msgId, msg, &buf);
    
    // 广播
    networkServer_->broadcast(buf.retrieveAllAsString());
}

void BaseServer::closeSession(uint64_t sessionId) {
    networkServer_->closeSession(sessionId);
}

SessionPtr BaseServer::getSession(uint64_t sessionId) {
    return networkServer_->getSession(sessionId);
}

void BaseServer::handleSessionConnected(const SessionPtr& session) {
    LOG_INFO << "Session connected: " << session->sessionId();
    
    // 调用子类回调
    onSessionConnected(session);
}

void BaseServer::handleSessionDisconnected(const SessionPtr& session) {
    LOG_INFO << "Session disconnected: " << session->sessionId();
    
    // 调用子类回调
    onSessionDisconnected(session);
}

void BaseServer::handleSessionMessage(const SessionPtr& session,
                                      Buffer* buf,
                                      Timestamp time) {
    // 循环处理所有完整的消息包（处理粘包）
    while (buf->readableBytes() >= protocol::PacketHeader::kHeaderSize) {
        // 解码消息
        uint16_t msgId;
        std::string data;
        int ret = protocol::MessageCodec::decode(buf, msgId, data);
        
        if (ret > 0) {
            // 成功解码一个完整消息
            LOG_DEBUG << "Received message: sessionId=" << session->sessionId()
                     << ", msgId=" << msgId
                     << ", size=" << data.size();
            
            // 分发消息
            dispatcher_.dispatch(session, msgId, data, time);
        } else if (ret == 0) {
            // 数据包不完整，等待更多数据
            break;
        } else {
            // 解码错误，关闭连接
            LOG_ERROR << "Decode error, closing session: " << session->sessionId();
            session->close();
            break;
        }
    }
}

} // namespace framework

